package com.hucsmn.examsystem.common.message;

import com.hucsmn.examsystem.util.BuildStrings;

import java.io.Serializable;
import java.time.Instant;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;

/**
 * 服务端记录登陆消息、考试消息的状态令牌。
 * <p>
 * 用于实现多个连接之间共享服务器状态，而 Token 则是帮助服务器将连接与指定会话状态进行关联的令牌。
 */
public class Token implements Serializable {
    private static final long serialVersionUID = 2561262195341426526L;

    private static final int LENGTH = 16;
    private static final Random RNG = new Random();

    // 令牌时间戳、随机数据。

    private final long timestamp;
    private final byte[] bytes;

    public Token() {
        byte[] token = new byte[LENGTH];
        synchronized (RNG) {
            RNG.nextBytes(token);
        }
        this.timestamp = Instant.now().getEpochSecond();
        this.bytes = token;
    }

    public long lifetime() {
        long now = Instant.now().getEpochSecond();
        return now - timestamp;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Token token = (Token) o;
        return timestamp == token.timestamp && Arrays.equals(bytes, token.bytes);
    }

    @Override
    public int hashCode() {
        int result = Objects.hash(timestamp);
        result = 31 * result + Arrays.hashCode(bytes);
        return result;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder(2 * bytes.length + 17);
        BuildStrings.appendBytes(sb, bytes);
        sb.append('+').append(String.format("%016x", timestamp));
        return sb.toString();
    }
}
